<?php
namespace Plu\Library\Services\Redis\Room;

use Plu\Library\Services\ServiceBase;

class RoomRedis extends ServiceBase {
    //订阅数
    const key_of_followers = 'r:subscribe:count';

    //鲜花数
    const key_of_flowers   = "item:flower:count";

    const key_of_roomgrade = "r:grade";

    const key_of_live_room = "r:live:%s";

    const key_of_live_keys = "r:live:keys";

    // roomid => domain
    const key_of_id_domain = "r:id:domain:%s";

    // domain => roomid
    const key_of_domain_id = "r:domain:id:%s";

    // userid => roomid
    const key_of_user_room = "user:room:%s";

    // roomid => userid
    const key_of_room_user = "room:user:%s";

    const key_of_domain_user = "u:domain:id";

    const key_of_user_domain = "u:id:domain";

    //获取点赞数
    const key_of_sort_by_admire = "a:live:admire";

    //在线人数hash
    const key_of_live_online_set = "all:online:countv2";

    //总魅力值
    const key_of_glamours = "r:contribution";

    //绑定的品类
    const key_of_room_category = "room:originalcategoryid";

    //直播品类
    const key_of_room_game = "room:categoryid";

    const key_of_stream_ratelevel = "r:stream:ratelevel:dic:%s";

    const VECTOR_TTL = 600;

    /**
     * 获取单个个房间的鲜花数
     */
    public function getFlowers($roomId) {
        $redis = $this->getRedis("vector");
        
        return (int)$redis->hGet(self::key_of_flowers, $roomId);
    }

    /**
     * 获取单个房间的魅力值
     */
    public function getGlamours($roomId) {
        $redis = $this->getRedis("vector");
        
        return intval($redis->hGet(self::key_of_glamours, $roomId));
    }

    /**
     * @deprecated
     *
     * 现在获取订阅数 使用follow服务
     */
    public function getFollowers($roomId) {
        $redis = $this->getRedis("vector");

        return $redis->hGet(self::key_of_followers, $roomId);
    }

    /**
     * 获取主播等级
     */
    public function getGrade($roomId) {
        $redis = $this->getRedis("vector");

        return $redis->hGet(self::key_of_roomgrade, $roomId);
    }

    public function getGrades($roomIds) {
        if (!is_array($roomIds)) {
            $roomIds = array($roomIds);
        }
        if (empty($roomIds)) {
            return false;
        }

        $redis = $this->getRedis("vector");

        return $redis->getFieldsFromHash(self::key_of_roomgrade, $roomIds);
    }

    ///{{{ 通过roomId获取域名

    /**
     * @return dict( roomId => domain )
     */
    public function getDomains($roomIds) {
        if (!is_array($roomIds)) {
            $roomIds = array($roomIds);
        }
        if (empty($roomIds)) {
            return false;
        }

        $redis = $this->getRedis("vector_cluster");

        $keys = array_map(function($roomId) {
            return sprintf(self::key_of_id_domain, $roomId);
        }, $roomIds);

        $domains = $redis->getFieldsWithCache($keys, self::VECTOR_TTL);

        return array_combine($roomIds, $domains);
    }

    /**
     * 获取单个房间的域名
     */
    public function getDomain($roomId) {
        $redis = $this->getRedis("vector_cluster");

        return $redis->getFieldWithCache(sprintf(self::key_of_id_domain, $roomId));
    }
    ///}}}

    ///{{{ 通过域名获取roomId

    public function getRoomIds($domains) {
        if (!is_array($domains)) {
            $domains = array($domains);
        }

        if (empty($domains)) {
            return false;
        }

        $redis = $this->getRedis("vector_cluster");

        $keys = array_map(function($domain) {
            return sprintf(self::key_of_domain_id, $domain);
        }, $domains);

        $roomIds = $redis->getFieldsWithCache($keys, self::VECTOR_TTL);

        return array_combine($domains, array_map(intval, $roomIds));
    }

    /**
     * 获取单个房间的roomid
     */
    public function getRoomId($domain) {
        $redis = $this->getRedis("vector_cluster");

        return (int)$redis->getFieldWithCache(sprintf(self::key_of_domain_id, $domain));
    }
    ///}}}

    ///{{{ 通过uid获取RoomId
    /**
     * @return dict( $uid => roomid )
     */
    public function getRoomIdsByUids($uids) {
        if (!is_array($uids)) {
            $uids = array($uids);
        }

        if (empty($uids)) {
            return false;
        }

        $redis = $this->getRedis("vector_cluster");
        $keys = array_map(function($uid) {
            return sprintf(self::key_of_user_room, $uid);
        }, $uids);

        $roomIds = $redis->getFieldsWithCache($keys, self::VECTOR_TTL);

        return array_combine( $uids, array_map(intval, $roomIds) );
    }

    public function getRoomIdByUid($uid) {
        $redis = $this->getRedis("vector_cluster");

        return (int)$redis->getFieldWithCache(sprintf(self::key_of_user_room, $uid));
    }
    ///}}}

    ///{{{ 通过uid获取domain
    
    /**
     * @return dict( $uid => $domain )
     */
    public function getDomainsByUids($uids) {
        if (!is_array($uids)) {
            $uids = array($uids);
        }

        if (empty($uids)) {
            return false;
        }

        $redis = $this->getRedis("vector");

        return $redis->getFieldsFromHash(self::key_of_user_domain, $uids);
    }

    public function getDomainByUid($uid) {
        $redis = $this->getRedis("vector");

        return $redis->hGet(self::key_of_domain_user, $uid);
    }
    ///}}}

    ///{{{ 通过roomId获取uid
    /**
     * @return dict( roomid => uid )
     */
    public function getUidsByRoomIds($roomIds) {
        if (!is_array($roomIds)) {
            $roomIds = array($roomIds);
        }

        if (empty($roomIds)) {
            return false;
        }

        $redis = $this->getRedis("vector_cluster");
        $keys = array_map(function($roomId) {
            return sprintf(self::key_of_room_user, $roomId);
        } , $roomIds);

        $uids = $redis->getFieldsWithCache($keys, self::VECTOR_TTL);

        return array_combine($roomIds, array_map(intval, $uids));
    }

    public function getUidByRoomId($roomId) {
        $redis = $this->getRedis("vector_cluster");

        return (int)$redis->getFieldWithCache(sprintf(self::key_of_room_user, $roomId));
    }
    ///}}}


    /**
     * 获取当前正在直播的roomids
     */
    public function getLiveRoomIds() {
        $cacheHandler = $this->getCacheHandler();
        $guid = "liveroomids";
        $roomIds = $cacheHandler->get($guid, 120);//1min

        if (empty($roomIds)) {
            if (isset($this->grpc)) {
                $liveService = $app->grpc->service("go.micro.srv.live");
                $rep = $liveService->GetOnlineRoomIDs();
                $roomIds = iterator_to_array($rep->getRoomIDs());
                $roomIds = array_values(array_unique($roomIds));
            } else {
                $rc = $this->getRedis("live_cluster")->getRedis();
                $masters = $rc->_masters();
                $redis = new \Redis();
                $roomIds = array();

                foreach ($masters as $node) {
                    $redis->connect($node[0], $node[1]);
                    $redis->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY);
                    $it = null; // Initialize our iterator to NULL
                    while($items = $redis->sScan(self::key_of_live_keys, $it, null, 500)) {
                        $roomIds = array_merge($roomIds, array_values($items));
                    }
                    $redis->close();
                }
            }

            $roomIds = array_map(intval, $roomIds);

            $cacheHandler->save($guid, $roomIds, 120);
        }

        return $roomIds;
    }

    /**
     * 获取当前正在直播的domain
     */
    public function getLiveDomains() {
        $cacheHandler = $this->getCacheHandler();
        $guid = "livedomains";
        $domains = $cacheHandler->get($guid, 60);//1min

        if (empty($domains)) {
            $roomIds = $this->getLiveRoomIds();
            $domains = $this->getDomains($roomIds);

            $domains = array_values(array_filter(array_values($domains)));
            $cacheHandler->save($guid, $domains, 60);
        }

        return $domains;
    }

    /**
     * 获取当前正在直播的uids
     */
    public function getLiveUserIds() {
        $cacheHandler = $this->getCacheHandler();
        $guid = "liveuserids";
        $userIds = $cacheHandler->get($guid, 60);//1min

        if (empty($userIds)) {
            $roomIds = $this->getLiveRoomIds();
            $userIds = $this->getUidsByRoomIds($roomIds);

            $userIds = array_values(array_filter(array_values($userIds)));
            $cacheHandler->save($guid, $userIds, 60);
        }

        return $userIds;
    }

    /**
     * 获取所有直播房间
     */
    public function getAllLives() {
        $roomIds = $this->getLiveRoomIds();
        for ($c = 0, $len = count($roomIds); $c < $len; $c++) {
            $info = $this->getLiveInfo($roomIds[$c]);
            if (empty($info)) {
                continue;
            }
            yield $info;
        }
    }

    /**
     * 获取所有直播的数量
     */
    public function getLivesCount() {
        $redis = $this->getRedis("live_cluster");

        return (int)$redis->sCard(self::key_of_live_keys);
    }

    /**
     * 根据一个roomId获取直播信息
     */
    public function getLiveInfo($roomId) {
        $redis = $this->getRedis("live_cluster");
        $item = $redis->get(sprintf(self::key_of_live_room, $roomId));

        return json_decode($item, true);
    }

    /**
     * 根据多个roomId获取多个直播信息
     */
    public function getMultiLiveInfo($roomIds) {
        $items = [];

        for ($c = 0, $len = count($roomIds); $c < $len; $c++) {
            $info = $this->getLiveInfo($roomIds[$c]);
            if (empty($info)) {
                continue;
            }
            $items = $info;
        }

        return $items;
    }

    /**
     * 获取所有房间的在线人数
     */
    public function getAllOnlineCount() {
        $data = array();

        $redis = $this->getRedis("live")->getRedis();
        $redis->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY);
        $it = null; // Initialize our iterator to NULL
    
        while($items = $redis->hScan(self::key_of_live_online_set, $it, null, 500)) {
            foreach ($items as $roomId => $views) {
                $data[$roomId] = (int)$views;
            }
        }

        return $data;
    }

    /**
     * 根据roomId获取在线人数
     *
     * @return dict( roomid => viewers )
     */
    public function getViewers($roomIds) {
        if (!is_array($roomIds)) {
            $roomIds = array($roomIds);
        }

        if (empty($roomIds)) {
            return false;
        }

        $redis = $this->getRedis("live");
        
        return array_map(intval, $redis->getFieldsFromHash(self::key_of_live_online_set, $roomIds));
    }

    public function getViewer($roomId) {
        $redis = $this->getRedis("live");
        return (int)$redis->hGet(self::key_of_live_online_set, $roomId);
    }

    public function getAdmire($roomId) {
        $redis = $this->getRedis("live");

        return (int)$redis->zScore(self::key_of_sort_by_admire, $roomId);
    }

    // 根据roomId获取绑定的游戏品类
    public function getOriginalGameId($roomId) {
        $redis = $this->getRedis("cache");

        return (int)$redis->hGet(self::key_of_room_category, $roomId);
    }

    /**
     * 获取签约品类
     *
     * @return dict( roomid => gameid )
     */
    public function getOriginalGameIds($roomIds) {
        if (!is_array($roomIds)) {
            $uids = array($roomIds);
        }

        if (empty($roomIds)) {
            return false;
        }

        $redis = $this->getRedis("cache");

        return $redis->getFieldsFromHash( self::key_of_room_category, $roomIds);
    }

    /**
     * 根据roomId获取正在直播的roomId
     */
    public function getLiveGameId($roomId) {
        $redis = $this->getRedis("cache");

        return (int)$redis->hGet(self::key_of_room_game, $roomId);
    }

    public function getStreamQuality($roomId) {
        $guid = sprintf(self::key_of_stream_ratelevel, $roomId);

        $redis = $this->getRedis("live_cluster");

        $d = $redis->getFieldWithCache($guid, self::VECTOR_TTL);

        return json_decode($d, true);
    }

    public function getStreamQualityByRoomIds($roomIds) {
        if (!is_array($roomIds)) {
            $uids = array($roomIds);
        }

        if (empty($roomIds)) {
            return false;
        }

        $redis = $this->getRedis("live_cluster");
        $keys = array_map(function($roomId) {
            return sprintf(self::key_of_stream_ratelevel, $roomId);
        } , $roomIds);

        $items = $redis->getFieldsWithCache($keys, self::VECTOR_TTL);
        
        $data = array_map(json_decode, $items, array_fill(0, count($items), 1));

        return array_combine($roomIds, $data);
    }
}
